package com.ruoyi.me.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ProcessStopException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.biz.ResultSaveModule;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.me.mapper.DifferentSolarModelMapper;
import com.ruoyi.me.service.DifferentSolarModelService;
import com.ruoyi.me.service.SpatialIndexForecastService;
import com.ruoyi.utils.TableUtils;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class DifferentSolarModelServiceImpl implements DifferentSolarModelService {
    @Value("${python.me.solar.path}")
    private String solarPath;
    @Value("${python.me.solar.name}")
    private String solarName;
    @Value("${python.me.solar.iniPath}")
    private String iniPath;
    @Value("${python.me.solar.jsonPath}")
    private String jsonPath;
    @Resource
    DifferentSolarModelMapper differentSolarModelMapper;
    @Override
    public AjaxResult testAdd(String path) {
        //进行文件信息添加
        try {
            Map<String, Object> vaMap = new HashMap<>();
            String[] args = {"CHAMP", "GOCE", "GRACEA", "GRACEB", "GRACEFO", "SWARMA", "SWARMB", "SWARMC"};
            List<String> sateList = Arrays.asList(args);
            Map<String, Object> maps = new HashMap<>();
            ObjectMapper mapper = new ObjectMapper();
            maps = mapper.readValue(new File(path), Map.class);
            List<String> tiList = new ArrayList<>();
            Map<String, Object> sateColor = new HashMap<>();
            for (String satellite : args) {
                List<String> col = new ArrayList<>();
                List<String> time = (List<String>) ((Map) maps.get(satellite)).get("time");
                for (String str : time) {
                    String[] arg = str.split("#");
                    tiList.add(arg[0]);
                    col.add(arg[1]);
                }
                List<String> color =  col.stream().distinct().collect(Collectors.toList());
                sateColor.put(satellite, color);
            }
            //进行日期去重排序
            List<String> timeList = tiList.stream().distinct().collect(Collectors.toList());
            Collections.sort(timeList, (a, b) -> a.compareTo(b));
            //遍历每一个卫星下的数据对于缺失的数据设置为null
            for (String satellite : sateList) {
                Map<String, Object> resMap = new HashMap<>();
                Map<String, Object> mp = new HashMap<>();
                Double avgHeight = Double.valueOf(((Map<String, Object>) maps.get(satellite)).get("avgHeight").toString());
                List<String> time = (List<String>) ((Map) maps.get(satellite)).get("time");
                Map<String, Object> timeY = new HashMap<>();
                for (String str : time) {
                    String[] arg = str.split("#");
                    timeY.put(arg[0], arg[1]);
                }
                //进行时间匹配
                for (String color : (List<String>) sateColor.get(satellite)) {
                    List<Object> value = new ArrayList<>();
                    for (String t : timeList) {
                        if (timeY.containsKey(t) && timeY.get(t).equals(color)) {
                            value.add(avgHeight);
                        } else {
                            value.add("null");
                        }
                    }
                    mp.put(color, value);
                }
                resMap.put(satellite, mp);
                Map<String,Object> timeMap = new HashMap<>();
                timeMap.put("time",timeList);
                //进行数据入库处理
                differentSolarModelMapper.testAdd(SequenceBuilder.sequenceId(), JSON.toJSONString(resMap), new Date(), satellite, JSON.toJSONString(timeMap));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

//            Map<String, Object> vaMap = new HashMap<>();
//            String[] args = {"CHAMP", "GOCE", "GRACEA", "GRACEB", "GRACEFO", "SWARMA", "SWARMB", "SWARMC"};
//            List<String> sateList = Arrays.asList(args);
//            Map<String, Object> maps = new HashMap<>();
//            ObjectMapper mapper = new ObjectMapper();
//            maps = mapper.readValue(new File(path), Map.class);
//            List<String> tiList = new ArrayList<>();
//            Map<String, Object> sateColor = new HashMap<>();
//            for (String satellite : args) {
//                List<String> col = new ArrayList<>();
//                List<String> time = (List<String>) ((Map) maps.get(satellite)).get("time");
//                for (String str : time) {
//                    String[] arg = str.split("#");
//                    tiList.add(arg[0]);
//                    col.add(arg[1]);
//                }
//                List<String> color =  col.stream().distinct().collect(Collectors.toList());
//                sateColor.put(satellite, color);
//            }
//            //进行日期去重排序
//            List<String> timeList = tiList.stream().distinct().collect(Collectors.toList());
//            Collections.sort(timeList, (a, b) -> a.compareTo(b));
//            //遍历每一个卫星下的数据对于缺失的数据设置为null
//            for (String satellite : sateList) {
//                Map<String, Object> resMap = new HashMap<>();
//                Map<String, Object> mp = new HashMap<>();
//                Double avgHeight = Double.valueOf(((Map<String, Object>) maps.get(satellite)).get("avgHeight").toString());
//                List<String> time = (List<String>) ((Map) maps.get(satellite)).get("time");
//                Map<String, Object> timeY = new HashMap<>();
//                for (String str : time) {
//                    String[] arg = str.split("#");
//                    timeY.put(arg[0], arg[1]);
//                }
//                List<Object> colorValue = new ArrayList<>();
//                for (int i = 0; i< timeList.size() ; i++) {
//                    Map<String, Object> map = new HashMap<>();
//                    if (timeY.containsKey(timeList.get(i))) {
//                        colorValue.add(avgHeight);
//                    } else {
//                        colorValue.add("null");
//                    }
//                }
//                List<Map<String, Object>> colorList = new ArrayList<>();
//                //进行时间匹配
//                boolean flag = true;
//                boolean flg = true;
//                for (String color : (List<String>) sateColor.get(satellite)) {
//                    List<Object> value = new ArrayList<>();
//                    for (int i = 0; i< timeList.size() ; i++) {
//                        Map<String, Object> map = new HashMap<>();
//                        if (timeY.containsKey(timeList.get(i)) && timeY.get(timeList.get(i)).equals(color)) {
//                            value.add(avgHeight);
//                        } else {
//                            value.add("null");
//                        }
//                    }
//                    List<Integer> index = new ArrayList<>();
//                    for (int i = 0; i<value.size(); i++){
//                        if (!value.get(i).toString().equals("null")){
//                            index.add(i);
//                        }
//                    }
//                    int start = 0;
//                    int end = 0;
//                    for (int i = 1; i < index.size(); i++) {
//                        Map<String, Object> map = new HashMap<>();
//                        if (index.get(i) - index.get(i- 1) > 1) {
//                            if (i - 1 > start) {
//                                end = i - 1;
//                                if (flag){
//                                    map.put("gt",index.get(start));
//                                    flag = false;
//                                }else {
//                                    map.put("gt",index.get(start)-1);
//                                }
//                                map.put("lte",index.get(end));
//                                map.put("color",color);
//                                colorList.add(map);
//                            }
//                            start = i;
//                        }
//                    }
//                    // 打印最后一个区间
//                    Map<String, Object> map1 = new HashMap<>();
//                    if (index.size() - 1 > start) {
//                        if (flg){
//                            map1.put("gt",index.get(start));
//                            flg = false;
//                        }else {
//                            map1.put("gt",index.get(start)-1);
//                        }
//                        map1.put("lte",index.get(index.size()-1));
//                        map1.put("color",color);
//                        colorList.add(map1);
//                    }
////                    resMap.put(color, value);
//                }
//                mp.put("data", colorValue);
//                mp.put("color", colorList);
//                resMap.put(satellite, mp);
//                Map<String,Object> timeMap = new HashMap<>();
//                timeMap.put("time",timeList);
//                //进行数据入库处理
////                differentSolarModelMapper.testAdd(SequenceBuilder.sequenceId(), JSON.toJSONString(resMap), new Date(), satellite, JSON.toJSONString(timeMap));
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        return null;
    }

    @Override
    public AjaxResult getInitialData() {
        List<Map<String, Object>> list = differentSolarModelMapper.getInitialData();
        Map<String, Object> resMap = new HashMap<>();
        for (Map<String, Object> map : list) {
            resMap.putAll(JSON.parseObject(map.get("JSON_DATA")+"",Map.class));
        }
        resMap.putAll(JSON.parseObject(list.get(0).get("JSON_TIME")+"",Map.class));
        return AjaxResult.success("获取数据成功",resMap);
    }

    @Override
    public AjaxResult getCalculateResult(Map<String, Object> map) throws ProcessStopException {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String sseId = map.get("sseId")+"";
        sseId+=loginUser.getUsername();
        map.put("iniPath",iniPath);
        String json = jsonPath+new Date().getTime()+".json";
        //生成json文件
        FileUtils.createJson(json, map);
        List<String> command = new ArrayList<>();
        command.add("python");
        //给调用python 命令中加上参数（-u）代表-u代表不通过缓存，直接输出,或者python代码print 结束后执行刷新缓冲区操作sys.stdout.flush()
        command.add("-u");
        command.add(solarPath+solarName);
        command.add(json);
        command.add(iniPath);
        System.out.println("python"+ " -u "+solarPath+solarName+ " "+json +" "+ iniPath);
        String results = ExecUtil.execPython(command, sseId);
        if (results.contains("###")){
            System.out.println(results);
            results = results.split("###")[1];
        }
        if (results.equals("error")){
            SseEmitterUtils.sendMessage(sseId,"100");
            SseEmitterUtils.remove(sseId);
            return AjaxResult.warn("选择时间有误，请重新选择");
        }
        List<String> timeList = (List<String>) map.get("time");
        List<String> modelList = (List<String>) map.get("model");
//        //调用python程序
        System.out.println(command.get(0)+" "+command.get(1)+" "+command.get(2)+" "+command.get(3));
        //获取参数中方法名
        Map<String, Object> reMap;
        Map<String, Object> resMap = new HashMap<>();
        //获取卫星名称
        String[] satellite = ((List<String>)map.get("satellite")).get(0).toString().split("_");
        //进行文件内容读取
//        String results = "C:\\Users\\zys\\Desktop\\Different_solar_activity_Result.txt";
        try {
            ObjectMapper mapper = new ObjectMapper();
            reMap = mapper.readValue(new File(results), Map.class);
            Map<String, Object> dataMap = (Map<String, Object>) reMap.get("dataList");
            Map<String, Object> errorData = (Map<String, Object>) reMap.get("errorData");
            Map<String, Object> obsSimulate = new HashMap<>();
            List<Map<String, Object>> tableList = new ArrayList<>();
            List<String> xList = new ArrayList<>();
            Map<String, Object> error = new HashMap<>();
            Map<String, Object> barChart = new HashMap<>();
            String[] heads = {"satellite","model","absolute_error","relative_error","root_mean_square_error","corrCoee"};
            List<String> hList = Arrays.asList(heads);
            String name = "";
            List<Map<String, Object>> headList = new ArrayList<>();
            for (String  head : hList) {
                Map<String, Object> headMp = new HashMap<>();
                switch (head) {
                    case "satellite":
                        name = "年份（卫星）";
                        headMp.put(head,name);
                        break;
                    case "model":
                        name = "模型";
                        headMp.put(head,name);
                        break;
                    case "absolute_error":
                        name = "平均绝对误差";
                        headMp.put(head,name);
                        break;
                    case "relative_error":
                        name = "平均相对误差";
                        headMp.put(head,name);
                        break;
                    case "root_mean_square_error":
                        name = "均方根";
                        headMp.put(head,name);
                        break;
                    case "corrCoee":
                        name = "相关系数";
                        headMp.put(head,name);
                        break;
                }
                headList.add(headMp);
            }
            for (String time : timeList) {
                //获取时间下观测值
                //拼装第一个表格数据
                Map<String, Object> predCompareObs = new HashMap<>();
                predCompareObs.put("obsData", dataMap.get(time+"_Density"));
                predCompareObs.put("preData", dataMap.get(time+"_simuDensity"));
                predCompareObs.put("time", dataMap.get(time+"_Time"));
                obsSimulate.put(time, predCompareObs);
                Map<String, Object> errorMap = new HashMap<>();
                Map<String, Object> absoluteMap = new HashMap<>();
                Map<String, Object> relativeMap = new HashMap<>();
                //拼装第一个echars
                for (String model : modelList ) {
                    //绝对误差、相对误差
                    absoluteMap.put(model, errorData.get(time+"#"+model+"#absolute_error#result："));
                    relativeMap.put(model, errorData.get(time+"#"+model+"#relative_error#result："));
                    //拼装表格数据绝对误差、相对误差、均方根误差置信度区间
                    Map<String, Object> tableMap = new HashMap<>();
                    tableMap.put("satellite", time+"年("+satellite[satellite.length-1]+"卫星)");
                    tableMap.put("model", model);
                    tableMap.put("absolute_error", errorData.get(time+"#"+model+"#absolute_error#confidenceInterval："));
                    tableMap.put("relative_error", errorData.get(time+"#"+model+"#relative_error#confidenceInterval："));
                    tableMap.put("root_mean_square_error", errorData.get(time+"#"+model+"#root_mean_square_error#result："));
                    tableMap.put("corrCoee", errorData.get(time+"#"+model+"#corrCoee："));
                    tableMap.put("year", time);
                    tableList.add(tableMap);
                }
                errorMap.put("absolute_error",absoluteMap);
                errorMap.put("relative_error",relativeMap);
                errorMap.put("time",dataMap.get(time+"_Time"));
                error.put(time, errorMap);
                //拼装柱状图X轴
                xList.add(time);
            }
            barChart.put("X", xList);
            //拼装柱状图Y轴
            Map<String, Object> absoluteAver = new HashMap<>();
            Map<String, Object>  relativeAver = new HashMap<>();
            Map<String, Object>  meanAver = new HashMap<>();
            Map<String, Object>  corrCoee = new HashMap<>();
            for (String model : modelList ) {
                List<Object> absoluteList = new ArrayList<>();
                List<Object> relativeList = new ArrayList<>();
                List<Object> meanList = new ArrayList<>();
                List<Object> corrList = new ArrayList<>();
                for (String time : timeList) {
                    absoluteList.add(errorData.get(time+"#"+model+"#absolute_error#averageResult："));
                    relativeList.add(errorData.get(time+"#"+model+"#relative_error#averageResult："));
                    meanList.add(errorData.get(time+"#"+model+"#root_mean_square_error#result：")+"");
                    corrList.add(errorData.get(time+"#"+model+"#corrCoee：")+"");
                }
                absoluteAver.put(model, absoluteList);
                relativeAver.put(model, relativeList);
                meanAver.put(model, meanList);
                corrCoee.put(model, corrList);
            }
            barChart.put("absolute_error", absoluteAver);
            barChart.put("relative_error", relativeAver);
            barChart.put("root_mean_square_error", meanAver);
            barChart.put("corrCoee", corrCoee);
            //拼装表格内容
            resMap.put("obsSimulate", obsSimulate);
            resMap.put("error", error);
            resMap.put("errorData", barChart);
            resMap.put("tableData", tableList);
            resMap.put("headList",headList);
            //拼装最优模型推荐内容
            List<String> bestMList = (List<String>) reMap.get("evalResult");
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i<bestMList.size(); i++) {
                String[] value = bestMList.get(i).split("#");
                stringBuilder.append(value[1]).append("年").append("最优模型为：").append(value[3]).append("；");
            }
            resMap.put("bestModel",stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString());

            List<String> list = Stream.of(results).collect(Collectors.toList());
            resMap.put("resultData", JSONUtil.toJsonStr(list));
            resMap.put("module", ResultSaveModule.MODEL_ASSESS);
//            resMap.put("submodule", ResultSaveModule.MODEL_ASSESS_SOLAR);

        } catch (Exception e) {
            e.printStackTrace();
        }
        SseEmitterUtils.sendMessage(sseId,"100");
        SseEmitterUtils.remove(sseId);
        return AjaxResult.success("获取成功",resMap);
    }

    @Override
    public AjaxResult download(Map<String, Object> map) {
        //进行数据解析
        //获取时间列表
//        List<String> timeList = (List<String>) map.get("timeList");
        TableUtils.createMeSpatialWord(map,null);
        return null;
    }

    @Override
    public SseEmitter push(String id, String flag) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        return SseEmitterUtils.connect(id+loginUser.getUsername(), flag);
    }


}
